# -*- coding: utf-8 -*-
"""
Created on Fri Dec 17 14:58:26 2021

@author: 刘长奇
"""

import numpy as np
import torch
from torch import nn
from torch.autograd import Variable

train_data=np.load("t10k-images.npy")#60000,784
train_label=np.load("t10k-labels.npy")#60000
test_data=np.load("train-images.npy")#10000,784
test_label=np.load("train-labels.npy")#10000

def ph_conv(x):
    '''卷积'''
    n=np.shape(x)[0]
    conv1 = nn.Conv2d(1, 1, 3, bias=False) # 定义卷积，1通道，1步长，3*3卷积核
    sobel_kernel = np.array(
    [[-1, -1, -1], 
     [-1, 8, -1], 
     [-1, -1, -1]
     ], dtype='float32') # 定义轮廓检测算子
    sobel_kernel = sobel_kernel.reshape((1, 1, 3, 3)) # 适配卷积的输入输出
    conv1.weight.data = torch.from_numpy(sobel_kernel) # 给卷积的 kernel 赋值
    temp=[]
    for i in range(n):
        t=torch.from_numpy(x[i])#转化成张量
        t=t.float()
        num=np.shape(x[i])[0]
        t=t.reshape(1,1,int(num**0.5),int(num**0.5))
        edge1 = conv1(Variable(t)) # 作用在图片矩阵上,输出同样是tensor的张量形式
        edge1 = edge1.detach().numpy()
        edge1=edge1.reshape(1,-1)
        edge1=np.squeeze(edge1,axis=(0,))
        edge1=list(edge1)
        temp.append(edge1)
    return temp

def ph_pool(x):
    '''池化'''
    pool1 = nn.MaxPool2d(2, 1)#池化窗口为2，移动步长为1
    n=np.shape(x)[0]
    temp=[]
    for i in range(n):
        t=torch.from_numpy(x[i])#转化成张量
        t=t.float()
        num=np.shape(x[i])[0]
        t=t.reshape(1,1,int(num**0.5),int(num**0.5))
        small_im1 = pool1(Variable(t))# 作用在图片矩阵上,输出同样是tensor的张量形式
        edge1 = small_im1.detach().numpy()
        edge1=edge1.reshape(1,-1)
        edge1=np.squeeze(edge1,axis=(0,))
        edge1=list(edge1)
        temp.append(edge1)
    return temp

depth=2 #定义卷积池化层数
t1=np.array(ph_conv(train_data))
t1=np.array(ph_pool(t1))
t2=np.array(ph_conv(test_data))
t2=np.array(ph_pool(t2))
#卷积池化网络
for i in range(depth-1):
    t1=np.array(ph_conv(t1))
    t1=np.array(ph_pool(t1))
    t2=np.array(ph_conv(t2))
    t2=np.array(ph_pool(t2))
    

print(np.shape(t1))
#神经网络进行拟合
from sklearn.neural_network import MLPClassifier
clf_class= MLPClassifier(solver='adam', learning_rate_init=0.00005,activation='logistic', alpha=1e-5,hidden_layer_sizes=(180,), random_state=1,max_iter=2000)
clf_class.fit(t1,train_label)
#sklearn神经网络学习，隐藏层两层，第一层30个节点，第二层24个节点，最多迭代2000次

y_pred=[]
j=0
for i in range(np.shape(test_data)[0]):
    y_pred.append(clf_class.predict([t2[i]]))
for i in range(np.shape(test_data)[0]):
    if y_pred[i]==test_label[i]:
        j=j+1
print(j/10000)
#训练集准确率计算：0.8519'''
    
        
        
        
        
        
        
        
    
